// numeric standard header -*-c++-*-
// Copyright 2003-2010 IAR Systems AB. 
#ifndef _NUMERIC_
#define _NUMERIC_

#ifndef _SYSTEM_BUILD
#pragma system_include
#endif

#include <iterator>
_STD_BEGIN

// TEMPLATE FUNCTION accumulate
template<class _InIt, class _Ty> inline
_Ty accumulate(_InIt _First, _InIt _Last, _Ty _Val)
{       // return sum of _Val and all in [_First, _Last)
  for (; _First != _Last; ++_First)
    _Val = _Val + *_First;
  return (_Val); 
}

// TEMPLATE FUNCTION accumulate WITH BINOP
template<class _InIt, class _Ty, class _Fn2> inline
_Ty accumulate(_InIt _First, _InIt _Last, _Ty _Val, _Fn2 _Func)
{       // return sum of _Val and all in [_First, _Last), using _Func
  for (; _First != _Last; ++_First)
    _Val = _Func(_Val, *_First);
  return (_Val); 
}

// TEMPLATE FUNCTION inner_product
template<class _InIt1, class _InIt2, class _Ty> inline
_Ty inner_product(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _Ty _Val)
{       // return inner product of sequences
  for (; _First1 != _Last1; ++_First1, ++_First2)
    _Val = _Val + *_First1 * *_First2;
  return (_Val); 
}

// TEMPLATE FUNCTION inner_product WITH BINOPS
template<class _InIt1, class _InIt2, class _Ty,
         class _Fn21, class _Fn22> inline
_Ty inner_product(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _Ty _Val,
                  _Fn21 _Func1, _Fn22 _Func2)
{       // return inner product of sequences, using _Func1 and _Func2
  for (; _First1 != _Last1; ++_First1, ++_First2)
    _Val = _Func1(_Val, _Func2(*_First1, *_First2));
  return (_Val); 
}

// TEMPLATE FUNCTION partial_sum
template<class _InIt, class _OutIt, class _Ty> inline
_OutIt _Partial_sum(_InIt _First, _InIt _Last,
                    _OutIt _Dest, _Ty *)
{       // compute partial sums into _Dest
  _Ty _Val = *_First;
  for (*_Dest = _Val; ++_First != _Last; *++_Dest = _Val)
    _Val = _Val + *_First;
  return (++_Dest); 
}

template<class _InIt, class _OutIt> inline
_OutIt partial_sum(_InIt _First, _InIt _Last,
                   _OutIt _Dest)
{       // compute partial sums into _Dest
  return (_First == _Last ? _Dest
          : _Partial_sum(_First, _Last, _Dest, _Val_type(_First))); 
}

// TEMPLATE FUNCTION partial_sum WITH BINOP
template<class _InIt, class _OutIt, class _Fn2, class _Ty> inline
_OutIt _Partial_sum(_InIt _First, _InIt _Last,
                    _OutIt _Dest, _Fn2 _Func, _Ty *)
{       // compute partial sums into _Dest, using _Func
  _Ty _Val = *_First;
  for (*_Dest = _Val; ++_First != _Last; *++_Dest = _Val)
    _Val = _Func(_Val, *_First);
  return (++_Dest); 
}

template<class _InIt, class _OutIt, class _Fn2> inline
_OutIt partial_sum(_InIt _First, _InIt _Last,
                   _OutIt _Dest, _Fn2 _Func)
{       // compute partial sums into _Dest, using _Func
  return (_First == _Last ? _Dest
          : _Partial_sum(_First, _Last, _Dest, _Func, _Val_type(_First))); 
}

// TEMPLATE FUNCTION adjacent_difference
template<class _InIt, class _OutIt, class _Ty> inline
_OutIt _Adjacent_difference(_InIt _First, _InIt _Last,
                            _OutIt _Dest, _Ty *)
{       // compute adjacent differences into _Dest
  _Ty _Val = *_First;

  for (*_Dest = _Val; ++_First != _Last; )
  {       // compute another difference
    _Ty _Tmp = *_First;
    *++_Dest = _Tmp - _Val;
    _Val = _Tmp; 
  }
  return (++_Dest); 
}

template<class _InIt, class _OutIt> inline
_OutIt adjacent_difference(_InIt _First, _InIt _Last,
                           _OutIt _Dest)
{       // compute adjacent differences into _Dest
  return (_First == _Last ? _Dest
          : _Adjacent_difference(_First, _Last, _Dest, _Val_type(_First))); 
}

// TEMPLATE FUNCTION adjacent_difference WITH BINOP
template<class _InIt, class _OutIt, class _Fn2, class _Ty> inline
_OutIt _Adjacent_difference(_InIt _First, _InIt _Last,
                            _OutIt _Dest, _Fn2 _Func, _Ty *)
{       // compute adjacent differences into _Dest, using _Func
  _Ty _Val = *_First;

  for (*_Dest = _Val; ++_First != _Last; )
  {       // compute another difference
    _Ty _Tmp = *_First;
    *++_Dest = _Func(_Tmp, _Val);
    _Val = _Tmp; 
  }
  return (++_Dest); 
}

template<class _InIt, class _OutIt, class _Fn2> inline
_OutIt adjacent_difference(_InIt _First, _InIt _Last,
                           _OutIt _Dest, _Fn2 _Func)
{       // compute adjacent differences into _Dest, using _Func
  return (_First == _Last ? _Dest : _Adjacent_difference(_First, _Last,
                                                         _Dest, _Func, 
                                                         _Val_type(_First))); 
}

_STD_END
#endif /* _NUMERIC_ */


/*
 * This file is derived from software bearing the following
 * restrictions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this
 * software and its documentation for any purpose is hereby
 * granted without fee, provided that the above copyright notice
 * appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation.
 * Hewlett-Packard Company makes no representations about the
 * suitability of this software for any purpose. It is provided
 * "as is" without express or implied warranty.
 */

/*
 * Copyright (c) 1992-2009 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 V5.04:0576 */
